#include "comm.hpp"
#include "Task.hpp"

// 需求：客户端中有N个进程，选择进程及特定任务，通过管道交给服务端运行，对接情况：N(clients) -> 1(sever)

class Command
{
public:
    Command(const string &fifo_name)
    {
        cout << "fifo_name: " << fifo_name << endl;
        _FifoName = fifo_name;
        createFifo(); // 创建命名管道
        openFifo();   // 打开命名管道
        cout << "_rfd: " << _rfd << endl;
        acceptCommand();
    }

    ~Command()
    {
        // 关闭 fd
        close(_rfd);

        // 删除命名管道文件
        unlink(_FifoName.c_str());
    }

    void createFifo()
    {
        umask(0); // 权限掩码设置

        // 创建命名管道
        int n = mkfifo(_FifoName.c_str(), mode);
        assert(n != -1);
        (void)n;
    }

    void openFifo()
    {
        // 打开管道（只读）
        _rfd = open(_FifoName.c_str(), O_RDONLY);
        assert(_rfd != -1);
        (void)_rfd;

        // Test
        cerr << "read " << _rfd << endl;
    }

    void acceptCommand()
    {
        while (true)
        {
            // 通过轮询的方式，不断读取任务信息
            char buffer[NUM] = {0};
            buffer[0] = 0; // 每次读取后，清空
            // 规定：读取任务代号

            ssize_t n = read(_rfd, buffer, sizeof(buffer) - 1); // 不读取 '\0'
            if (n && (buffer[0] - '0') != 3)
            {
                if (n == -1)
                {
                    cerr << "read fail! "
                         << "errno " << errno << " : strerror " << strerror(errno) << endl;
                    sleep(1);
                    continue;
                }

                int taskNum = buffer[0] - '0';

                Task().Execute(taskNum);
                sleep(1);
            }
            else
            {
                // 写端关闭，读端也可以关闭了
                cout << "客户端已关闭，服务端也将关闭" << endl;
                sleep(1);
                //break;
            }
        }
    }

private:
    int _rfd;
    string _FifoName;
};

// int main()
// {
//     Command c1(fifo_name1); // 创建对象
//     Command c2(fifo_name2);
//     Command c3(fifo_name3);

//     c1.acceptCommand();
//     c1.acceptCommand();
//     c1.acceptCommand();

//     // while(true)
//     // {
//     //     c1.acceptCommand();
//     //     c2.acceptCommand();
//     //     c3.acceptCommand();
//     // }

//     return 0;
// }